package customize

import (
	"encoding/base64"
	"encoding/json"
	"sort"
	"strings"
	"time"

	"gitcode.com/G-YT/baoyou/server/global"
	"gitcode.com/G-YT/baoyou/server/model/common/request"
	"gitcode.com/G-YT/baoyou/server/model/customize"
	customizeReq "gitcode.com/G-YT/baoyou/server/model/customize/request"
	"gorm.io/gorm"
)

type ConstitutionService struct {
}

var habitus = []string{
	"气虚",
	"气郁",
	"痰湿",
	"湿热",
	"阴虚",
	"阳虚",
	"血瘀",
	"特禀",
	"平和",
}

var birthdayConf = map[int]string{
	0: "血瘀",
	1: "气虚",
	2: "阴虚",
	3: "阳虚",
	4: "痰湿",
	5: "气虚",
	6: "湿热",
	7: "气郁",
	8: "气虚",
	9: "阴虚",
}

type KeyValue struct {
	Key   string
	Value int
}

func (constitutionService *ConstitutionService) QuestionConf() (data map[string]string, err error) {
	habitus := []string{
		"气虚",
		"气郁",
		"痰湿",
		"湿热",
		"阴虚",
		"阳虚",
		"血瘀",
		"特禀",
		"平和",
	}

	qConf := map[string]string{
		habitus[0] + "_1": "经常会感觉到疲惫、劳累，是这样吗？",
		habitus[0] + "_2": "有个风吹草动就感冒，还容易出汗，咳嗽、哮喘，以上症状至少有一样吗？",
		habitus[0] + "_3": "不爱说话，经常忘东忘西的，头晕，食欲不振，以上症状至少有一样吗？",
		habitus[0] + "_4": "肌肉或皮肤松软，肚子、胳膊、大腿都有赘肉，是这样吗？",

		habitus[1] + "_1": "经常感觉到焦虑，是这样吗？",
		habitus[1] + "_2": "经常腹胀、呕吐、乳房胀痛、排气较多，以上症状至少有一种吗？",
		habitus[1] + "_3": "多愁善感、总感慨或者发愁，精神不振、左右肋间痛，以上症状至少有一样吗？",
		habitus[1] + "_4": "您特别不爱活动，是这样吗？",

		habitus[2] + "_1": "您的体重超标吗？",
		habitus[2] + "_2": "经常浮肿、嗜睡、经常吐痰、口中黏腻、睡觉打鼾，以上症状至少有一样吗？",
		habitus[2] + "_3": "糖尿病、高脂血症、高血压或血压在三年前开始升高，以上症状至少有一样吗？",
		habitus[2] + "_4": "经常感觉到困乏，白天也想睡觉，是这样吗？",

		habitus[3] + "_1": "皮肤爱出油，是这样吗？",
		habitus[3] + "_2": "身上或脸上经常起痘，头发一天不洗就出油，身体异味大，以上症状至少有一样吗？",
		habitus[3] + "_3": "皮肤容易感染，生殖系统易感染，经常出现瘙痒， 以上症状至少有一样吗？",
		habitus[3] + "_4": "喜欢吃肥甘、辛辣，口味比较重的食物，是这样吗？",

		habitus[4] + "_1": "特别怕热，是这样吗？",
		habitus[4] + "_2": "口干、眼干、皮肤干、爱喝水、以上症状至少有一样吗？",
		habitus[4] + "_3": "经常出现溃疡，晚上睡觉容易出汗，便秘，以上症状至少有一样吗？",
		habitus[4] + "_4": "皮肤粗糙、不润滑，是这样吗？",

		habitus[5] + "_1": "特别怕冷，总穿的比别人多，是这样吗？",
		habitus[5] + "_2": "大便不成形，夜尿2次以上，性功能减退，失眠，以上症状至少有一样吗？",
		habitus[5] + "_3": "腰膝酸软，关节疾病，胸闷气短，心神不宁，甲减，以上症状至少有一样吗？",
		habitus[5] + "_4": "吃凉东西会不舒服，是这样吗？",

		habitus[6] + "_1": "有疼痛的症状，身体不是这儿疼就是那儿疼，是这样吗？",
		habitus[6] + "_2": "心脏病、静脉曲张、中风、经常出现皮肤淤青，以上症状至少有一样吗？",
		habitus[6] + "_3": "有包块结节，息肉、肿瘤，皮肤有明显色斑，以上症状至少有一样吗？",
		habitus[6] + "_4": "经常在刷牙的时候会出血，或者经常流鼻血吗，是这样吗？",

		habitus[7] + "_1": "您有过敏体质吗？",
		habitus[7] + "_2": "对某种物质过敏，皮肤经常出疹子，不感冒也流鼻涕，以上症状至少有一样吗？",
		habitus[7] + "_3": "哮喘、风团、紫癜、咽痒、鼻塞、荨麻疹、过敏性紫癜、血友病，以上症状至少有一样吗？",
		habitus[7] + "_4": "您有先天性的疾病吗？",

		habitus[8] + "_1": "您精力充沛，没有任何疾病吗？",
		habitus[8] + "_2": "您皮肤光滑，没有任何不适症状吗？",
		habitus[8] + "_3": "心态平稳，体态适中，是这样吗？",
		habitus[8] + "_4": "您对自然环境的变化和社会环境的变化适应力很强吗？",
	}
	return qConf, nil
}

// CreateConstitutionQuestionLog 创建体质检测记录
func (constitutionService *ConstitutionService) CreateConstitutionQuestionLog(constitutionQuestionLog *customize.ConstitutionQuestionLog) (logID uint, err error) {
	err = global.GVA_DB.Create(constitutionQuestionLog).Error
	logID = constitutionQuestionLog.ID
	return
}

// GetConstitutionInfo 计算用户体质信息
func (constitutionService *ConstitutionService) GetConstitutionInfo(results map[string]int, birthday time.Time) (userPhysique customize.UserConstitution, err error) {
	var data customize.UserConstitution
	item := make(map[string]int)
	// 获取年份
	year := birthday.Year()
	// 取最后一个数字
	lastDigit := year % 10
	for key, value := range results {
		decodedKey, _ := base64.StdEncoding.DecodeString(key)
		keys := strings.Split(string(decodedKey), "_")
		if value == 1 {
			if contains(keys[0], habitus) {
				if _, exists := item[keys[0]]; exists {
					item[keys[0]] += 25
				} else {
					item[keys[0]] = 25
				}
			}
		} else {
			if _, exists := item[keys[0]]; !exists {
				item[keys[0]] = 0
			}
		}
	}
	//fmt.Printf("item: %#v\n", item)
	mantissaKey := birthdayConf[lastDigit]
	item[mantissaKey] += 1
	encodedData := make(map[string]int)
	for key, value := range item {
		// 将键转换为base64编码
		encodedKey := base64.StdEncoding.EncodeToString([]byte(key))
		// 将转换后的键和原始值存储到新的map中
		encodedData[encodedKey] = value
	}

	jsonData, err := json.Marshal(encodedData)
	data.Score = string(jsonData)

	sortedItem := sortMapByValue(item)
	lastItem := sortedItem[len(sortedItem)-1]
	data.Constitution = lastItem.Key
	return data, err
}

// GetConstitutionID 根据体质名称获取体质ID
// Author [g-qs](https://github.com/g-qs)
func (constitutionService *ConstitutionService) GetConstitutionID(name string) (constitution customize.Constitution, err error) {
	err = global.GVA_DB.Where("name LIKE ?", "%"+name+"%").First(&constitution).Error
	return
}

// GetConstitutionQuestionLog 获取体质检测记录
func (constitutionService *ConstitutionService) GetConstitutionQuestionLog(condition map[string]interface{}, fields string) (constitutionQuestionLog customize.ConstitutionQuestionLog, err error) {
	err = global.GVA_DB.Select(fields).Where(condition).Order("created_at Desc").Limit(1).First(&constitutionQuestionLog).Error
	return
}

// GetConstitutionQuestionList 获取体质检测记录列表
func (constitutionService *ConstitutionService) GetConstitutionQuestionList(condition map[string]interface{}, fields string) (constitutionQuestionLog []customize.ConstitutionQuestionLog, err error) {
	err = global.GVA_DB.Select(fields).Where(condition).Order("created_at Desc").Find(&constitutionQuestionLog).Error
	return
}

// CreateConstitution 创建体质
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) CreateConstitution(constitution *customize.Constitution) (err error) {
	err = global.GVA_DB.Create(constitution).Error
	return err
}

// DeleteConstitution 删除体质
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) DeleteConstitution(constitution customize.Constitution) (err error) {
	err = global.GVA_DB.Delete(&constitution).Error
	return err
}

// DeleteConstitutionByIds 批量删除体质
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) DeleteConstitutionByIds(ids request.IdsReq) (err error) {
	err = global.GVA_DB.Delete(&[]customize.Constitution{}, "id in ?", ids.Ids).Error
	return err
}

// UpdateConstitution 更新体质
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) UpdateConstitution(constitution customize.Constitution) (err error) {
	err = global.GVA_DB.Save(&constitution).Error
	return err
}

// GetConstitution 根据id获取体质
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) GetConstitution(id uint) (constitution customize.Constitution, err error) {
	err = global.GVA_DB.Where("id = ?", id).First(&constitution).Error
	return
}

// GetConstitutionId 根据体质名称获取体质ID
// Author [g-qs](https://github.com/g-qs)
func (constitutionService *ConstitutionService) GetConstitutionId(name string) (constitution customize.Constitution, err error) {
	err = global.GVA_DB.Where("tz_name LIKE ?", "%"+name+"%").First(&constitution).Error
	return
}

// GetConstitutionInfoList 分页获取体质记录
// Author [G-YT](https://gitcode.com/G-YT)
func (constitutionService *ConstitutionService) GetConstitutionInfoList(info customizeReq.ConstitutionSearch) (list []customize.Constitution, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.GVA_DB.Model(&customize.Constitution{})
	var constitution []customize.Constitution
	// 如果有条件搜索 下方会自动创建搜索语句
	err = db.Count(&total).Error
	if err != nil {
		return
	}

	if limit != 0 {
		db = db.Limit(limit).Offset(offset)
	}

	err = db.Find(&constitution).Error
	return constitution, total, err
}

func (constitutionService *ConstitutionService) SetConstitutionArticle(req customizeReq.ConstitutionArticleReq) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("constitution_id = ?", req.ConstitutionID).Delete(&customize.ConstitutionArticle{}).Error; err != nil {
			return err
		}
		var constitutionArticles []customize.ConstitutionArticle
		for _, richText := range req.RichTexts {
			constitutionArticles = append(constitutionArticles, customize.ConstitutionArticle{
				ConstitutionID: req.ConstitutionID,
				ArticleID:      richText,
				Type:           "richText",
			})
		}
		for _, audio := range req.Audios {
			constitutionArticles = append(constitutionArticles, customize.ConstitutionArticle{
				ConstitutionID: req.ConstitutionID,
				ArticleID:      audio,
				Type:           "audio",
			})
		}
		for _, video := range req.Videos {
			constitutionArticles = append(constitutionArticles, customize.ConstitutionArticle{
				ConstitutionID: req.ConstitutionID,
				ArticleID:      video,
				Type:           "video",
			})
		}
		if len(constitutionArticles) == 0 {
			return nil
		}
		return tx.Create(&constitutionArticles).Error
	})
}

func (constitutionService *ConstitutionService) GetConstitutionArticle(constitutionID string) (constitutionArticle []customize.ConstitutionArticle, err error) {
	err = global.GVA_DB.Where("constitution_id = ?", constitutionID).Find(&constitutionArticle).Error
	return
}

func contains(item string, list []string) bool {
	for _, value := range list {
		if value == item {
			return true
		}
	}
	return false
}

func sortMapByValue(m map[string]int) []KeyValue {
	var sorted []KeyValue
	for k, v := range m {
		sorted = append(sorted, KeyValue{k, v})
	}
	sort.Slice(sorted, func(i, j int) bool {
		return sorted[i].Value < sorted[j].Value
	})
	return sorted
}
